import * as React from 'react';
import { Select, Tooltip, message } from 'antd';
import './ContentEditable.scss';

const ENTER_KEY = 13;

interface ContentProps {
  onChange: (content: any) => any;
  tip: string;
  tagName?: string;
  className?: string;
  children?: any;
  multiline?: boolean;
  separator?: string[];
  maxLen?: number;
}
interface ContentState {
  selectValues: string[];
}

export default class ContentEditable extends React.Component<ContentProps, ContentState> {
  static defaultProps: ContentProps = {
    onChange: () => {},
    tagName: 'div',
    children: null,
    className: '',
    tip: '',
    multiline: false,
    maxLen: 0,
  };

  constructor(props: ContentProps) {
    super(props);

    this.state = {
      selectValues: [],
    };
  }

  handleKeyDown = (e: any) => {
    e.stopPropagation();

    const { multiline } = this.props;
    const sel = window.getSelection();

    // the node that contains the caret
    const node = sel.anchorNode;

    if (e.keyCode === ENTER_KEY) {
      // prevent the browsers from inserting <div>, <p>, or <br> on their own
      e.preventDefault();

      if (multiline) {
        // the caret position inside the node
        const offset = sel.anchorOffset;

        // insert a '\n' character at that position
        const text = node.textContent || '';
        const textBefore = text.slice(0, offset);
        const textAfter = text.slice(offset) || ' ';

        node.textContent = `${textBefore}\n${textAfter}`;

        // position the caret after that new-line character
        const range = document.createRange();

        range.setStart(node, offset + 1);
        range.setEnd(node, offset + 1);

        // update the selection
        sel.removeAllRanges();
        sel.addRange(range);
      } else {
        e.currentTarget.blur();
      }
    }
  };

  // 对混淆选项根据maxLen控制字符串长度
  handleChange = (e: any) => {
    const { onChange, children: originContent, maxLen } = this.props;
    const newContent = e.currentTarget.textContent;

    if (maxLen) {
      const strArr = newContent.split(',');
      let isOk = true;
      for (let i = 0; i < strArr.length; i++) {
        if (strArr[i].length > maxLen) {
          isOk = false;
          break;
        }
      }
      if (!isOk) {
        message.error(`每个选项请不要超过${maxLen}个字符`);
        return;
      }
    }

    if (newContent !== originContent) {
      onChange(newContent);
    }
  };

  renderContentEditable() {
    const { tagName, className, tip, multiline } = this.props;
    const finalClassName = `content-editable ${className} ${
      multiline ? 'wrap-pre-wrap text-left line-height-2' : ''
    }`;

    return React.createElement(
      tagName || 'div',
      {
        className: finalClassName,
        placeholder: tip || 'Click to edit',
        contentEditable: 'plaintext-only',
        suppressContentEditableWarning: true,
        onBlur: this.handleChange,
        onKeyDown: this.handleKeyDown,
        onClick: (e: any) => {
          e.stopPropagation();
        },
      },
      this.props.children
    );
  }

  handleSelectChange = (selectValues: string[]) => {
    this.setState({
      selectValues,
    });
  };

  handleSelectDone = () => {
    const { selectValues } = this.state;
    const { onChange, children: originContent } = this.props;
    const newContentStr = selectValues.join(',');

    if (newContentStr !== originContent.join(',')) {
      onChange(selectValues);
    }
  };

  renderSelectable() {
    const { className, tip, separator, children } = this.props;
    let classes: string[] = ['content-editable', 'content-editable-select'];
    if (className) {
      classes.push(className);
    }
    if (children.length > 0) {
      classes.push('content-select-center');
    }

    return (
      <Select
        mode="tags"
        defaultValue={children}
        className={classes.join(' ')}
        placeholder={tip || '默认以,分隔(中文输入下，不要用空格作为分隔符)'}
        tokenSeparators={separator || [',', '，']}
        onChange={this.handleSelectChange}
        onBlur={this.handleSelectDone}
      />
    );
  }

  render() {
    const { tip, tagName } = this.props;

    return (
      <Tooltip placement="top" title={tip || '点击编辑'} key={this.props.children}>
        {tagName === 'select' ? this.renderSelectable() : this.renderContentEditable()}
      </Tooltip>
    );
  }
}
